#pragma once

#include "Generalization.h"

#include "Classifier.h"
#include "GeneralizationSet.h"

namespace uml {

const bool Generalization::isSubstitutable_default_ = true;
void Generalization::fromJson(const QJsonObject& json, QStringList& errorList) {
    if (json.isEmpty()) {
        return;
    }

    DirectedRelationship::fromJson(json, errorList);
    general_ = JsonSerializable::create<Classifier>(json.value("general"), errorList);

    JsonSerializable::fromJsonArray(generalizationSets_, "generalizationSets", json, errorList);
    isSubstitutable_ = json.value("isSubstitutable").toBool(isSubstitutable_default_);
    specific_ = JsonSerializable::create<Classifier>(json.value("specific"), errorList);

}

void Generalization::toJson(QJsonObject& json) {
    DirectedRelationship::toJson(json);
    if (general_) {
        QJsonObject general_json;
        general_->toJson(general_json);
        json.insert("general", general_json);
    }
    JsonSerializable::toJsonArray(generalizationSets_, "generalizationSets", json);
    if (isSubstitutable_ != isSubstitutable_default_) {
        json.insert("isSubstitutable", isSubstitutable_);
    }
    if (specific_) {
        QJsonObject specific_json;
        specific_->toJson(specific_json);
        json.insert("specific", specific_json);
    }
}

/// <summary>
/// general getter
/// The general classifier in the Generalization relationship.
/// </summary>
shared_ptr<Classifier> Generalization::general() const {
    return general_;
}

/// <summary>
/// general setter
/// The general classifier in the Generalization relationship.
/// </summary>
void Generalization::setGeneral(shared_ptr<Classifier> value) {
    general_ = value;
}

/// <summary>
/// generalizationSets getter
/// Represents a set of instances of Generalization.  A Generalization may appear in
/// many GeneralizationSets.
/// </summary>
vector<shared_ptr<GeneralizationSet>>& Generalization::generalizationSets() {
    return generalizationSets_;
}

/// <summary>
/// isSubstitutable getter
/// Indicates whether the specific Classifier can be used wherever the general
/// Classifier can be used. If true, the execution traces of the specific Classifier
/// shall be a superset of the execution traces of the general Classifier. If false,
/// there is no such constraint on execution traces. If unset, the modeler has not
/// stated whether there is such a constraint or not.
/// </summary>
bool Generalization::isSubstitutable() const {
    return isSubstitutable_;
}

/// <summary>
/// isSubstitutable setter
/// Indicates whether the specific Classifier can be used wherever the general
/// Classifier can be used. If true, the execution traces of the specific Classifier
/// shall be a superset of the execution traces of the general Classifier. If false,
/// there is no such constraint on execution traces. If unset, the modeler has not
/// stated whether there is such a constraint or not.
/// </summary>
void Generalization::setIsSubstitutable(bool value) {
    isSubstitutable_ = value;
}

/// <summary>
/// specific getter
/// The specializing Classifier in the Generalization relationship.
/// </summary>
shared_ptr<Classifier> Generalization::specific() const {
    return specific_;
}

/// <summary>
/// specific setter
/// The specializing Classifier in the Generalization relationship.
/// </summary>
void Generalization::setSpecific(shared_ptr<Classifier> value) {
    specific_ = value;
}

} // namespace uml
